package com.greateamd.timetableasy.client.widgets.event;

import java.util.Date;

import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.BlurEvent;
import com.google.gwt.event.dom.client.BlurHandler;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.logical.shared.ValueChangeEvent;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiConstructor;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.uibinder.client.UiHandler;
import com.google.gwt.uibinder.client.UiTemplate;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.CheckBox;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.Widget;
import com.google.gwt.user.datepicker.client.DateBox;
import com.greateamd.timetableasy.client.domain.EventType;
import com.greateamd.timetableasy.client.services.room.RoomService;
import com.greateamd.timetableasy.client.services.room.RoomServiceAsync;
import com.greateamd.timetableasy.client.services.user.UserService;
import com.greateamd.timetableasy.client.services.user.UserServiceAsync;
import com.greateamd.timetableasy.client.services.util.ServerCall;
import com.greateamd.timetableasy.client.widgets.MessagePopupPanel;
import com.greateamd.timetableasy.client.widgets.user.TeacherListBox;
import com.greateamd.timetableasy.domain.Event;

public class EventPanel extends Composite implements BlurHandler {
	
	@UiTemplate("EventPanel.ui.xml")
	interface EventPanelUIBinder extends UiBinder<Widget, EventPanel> {}
	private static EventPanelUIBinder uiBinder = GWT.create(EventPanelUIBinder.class);
	
	@UiField TextBox labelTb;
	@UiField EventModalityListBox modalityLb;
	@UiField EventTypeListBox typeLb;
	@UiField EventCampusManagerRoomListBox locationLb;
	@UiField Button checkRoomValidityBt;
	@UiField TeacherListBox teacherLb;
	@UiField Button checkTeacherValidityBt;
	@UiField DateBox dbStart;
	@UiField TextBox durationTb;
	@UiField CheckBox mandatory;
	@UiField CheckBox enabled;
	@UiField Button applyBt;
	
	private Event event = new Event();
	private boolean checkLocationValidity = false;
	private boolean checkTeacherValidity = false;
	
	public @UiConstructor EventPanel(final boolean readOnly) {
		initWidget(uiBinder.createAndBindUi(this));
		typeLb.setReadOnly(true);
		applyBt.setEnabled(false);
		if(!readOnly){
			locationLb.loadRooms();
			locationLb.addBlurHandler(this);
			teacherLb.addBlurHandler(this);
			durationTb.addBlurHandler(this);
		} else {
			checkRoomValidityBt.setVisible(false);
			checkTeacherValidityBt.setVisible(false);
			applyBt.setVisible(false);
			modalityLb.setReadOnly(true);
			locationLb.setReadOnly(true);
			teacherLb.setReadOnly(true);
			labelTb.setEnabled(false);
			dbStart.setEnabled(false);
			durationTb.setEnabled(false);
			mandatory.setEnabled(false);
			enabled.setEnabled(false);
		}
	}
	public EventPanel(boolean readOnly,final Event event) {
		this(readOnly);
		setEvent(event);
	}

	//---------------------------------------------------------------------
	//-------------------------- UI Action	
	private void setPanel(){
		labelTb.setValue(event.getLabel());
		locationLb.setValue(event.getLocation());
		modalityLb.setValue(event.getEventModality());
		typeLb.setValue(event.getEventType());
		dbStart.setValue(event.getStartDate());
		durationTb.setValue(String.valueOf(event.getDuration()));
		mandatory.setValue(event.isMandatory());
		enabled.setValue(event.isEnabled());
		teacherLb.setValue(event.getDispenser());
	}

	protected void resfreshValidity() {
		if(eventPanelIsValid()){
			applyBt.setEnabled(true);
		}
		else{
			applyBt.setEnabled(false);
		}
	}
	
	//---------------------------------------------------------------------
	//-------------------------- Handler
	@UiHandler("checkRoomValidityBt")
	void onCheckRoomBtClick(ClickEvent e){
		if(dbStart.getValue()==null ){
			Window.alert("Select a date, a room and a duration");
			return ;
		} else if( locationLb.getValue().isEmpty()){
			Window.alert("Select a room or set a custom location");
			return ;
		} else if( !locationLb.getValue().isEmpty() && locationLb.getSelectedRoom()==null){
			checkLocationValidity = true;
			checkRoomValidityBt.setVisible(false);
			resfreshValidity();
			new MessagePopupPanel("OK","This Event can be added to this room and date").show();
		}
		try{
			Integer.parseInt(durationTb.getValue());
		} catch (Exception ex) {
			Window.alert("Duration must be a integer");
			return;
		}
		new ServerCall<Boolean>() {

			@Override
			protected void callService(AsyncCallback<Boolean> asyncCallback) {
				RoomServiceAsync roomService = GWT.create(RoomService.class);
				//If this verification have to exclude a event id, (if the event is edited, do not take count of this event)
				roomService.getDisponibility(event.getId(),locationLb.getValue(), dbStart.getValue(), Integer.parseInt(durationTb.getValue()), asyncCallback);
			}

			@Override
			public void onSuccess(Boolean result) {
				checkLocationValidity = result;
				checkRoomValidityBt.setVisible(!result);
				resfreshValidity();
				if(result){
					new MessagePopupPanel("OK","This Event can be added to this room and date").show();
				} else {
					new MessagePopupPanel("Wrong","This Event cannot be added to this room and date").show();
				}
			}
		}.call();
	}
	
	@UiHandler("checkTeacherValidityBt")
	void onCheckTeacherBtClick(ClickEvent e){
		if(teacherLb.getValue().isEmpty()){
			new MessagePopupPanel("OK","You can add a event without dispenser/teacher").show();
			checkTeacherValidity = true;
			checkTeacherValidityBt.setVisible(false);
			resfreshValidity();
			return;
		} else if(dbStart.getValue()==null){
			Window.alert("Select a date, a teacher and a duration");
			return ;
		}
		try{
			Integer.parseInt(durationTb.getValue());
		} catch (Exception ex) {
			Window.alert("Duration must be a integer");
			return;
		}
		new ServerCall<Boolean>() {

			@Override
			protected void callService(AsyncCallback<Boolean> asyncCallback) {
				UserServiceAsync userService = GWT.create(UserService.class);
				userService.getTeacherDisponibility(event.getId(),teacherLb.getValue(), dbStart.getValue(), Integer.parseInt(durationTb.getValue()), asyncCallback);
			}

			@Override
			public void onSuccess(Boolean result) {
				checkTeacherValidity = result;
				checkTeacherValidityBt.setVisible(!result);
				resfreshValidity();
				if(result){
					new MessagePopupPanel("OK","This teacher not occupied at this time").show();
				} else {
					new MessagePopupPanel("Wrong","This teacher is occupied at this time").show();
				}
			}
		}.call();
	}
	
	@UiHandler("applyBt")
	void onSubmitBtClick(ClickEvent e){
		if(event==null)
			return;
		event.setLabel(labelTb.getValue());
		event.setLocation(locationLb.getValue());
		event.setEventType(typeLb.getEventTypeSelected());
		event.setEventModality(modalityLb.getEventModalitySelected());
		event.setStartDate(dbStart.getValue());
		event.setDuration(Integer.valueOf(durationTb.getValue()));
		event.setMandatory(mandatory.getValue());
		event.setEnabled(enabled.getValue());
		event.setDispenser(teacherLb.getValue());
	}
	
	@UiHandler("dbStart")
	void onDateValueChange(ValueChangeEvent<Date> e){
		removeValidity();
	}
	
	@Override
	public void onBlur(BlurEvent arg0) {
		removeValidity();
	}
	
	private void removeValidity(){
		checkTeacherValidity = false;
		checkLocationValidity = false;
		checkTeacherValidityBt.setVisible(true);
		checkRoomValidityBt.setVisible(true);
		resfreshValidity();
	}
	
	public boolean eventPanelIsValid() {
		if(!checkLocationValidity || !checkTeacherValidity ) return false;
		if( labelTb.getText().isEmpty() ) return false;
		if( modalityLb.getValue().isEmpty() ) return false;
		if( locationLb.getValue().isEmpty() ) return false;
		if( dbStart.getValue() == null ) return false;
		if( durationTb.getText().isEmpty()) return false;
		try{
			Integer.parseInt(durationTb.getText());
		}catch (Exception e) {
			return false;
		}
		return true;
	}
	
	/**
	 * If restriction, the panel force to chose the type arg for the event
	 * @param typeRestriction to force, null to remove restriction
	 */
	public void setEventTypeRestriction(final EventType typeRestriction){
		if(typeRestriction==null){
			typeLb.setEnabled(true);
			return;
		}
		typeLb.setValue(typeRestriction);
		typeLb.setEnabled(false);
	}
	
	public void setEvent(Event e){
		event = e;
		setPanel();
	}

	public Event getEvent() {
		return event;
	}
}
